// 赋值了对象的变量存储的不是对象本身，而是该对象“在内存中的地址”————换句话说就是对该对象的引用。

// 两个变量引用同一个对象时，它们才相等。
let a = {}
let b = a
console.log(a == b) // true
console.log(a === b) // true

// 两个不同变量的对象，它们不相等（即使看起来一样）。
let c = {}
let d = {}
console.log(c == d) // false

// *************************************************************************************************

// 注：对象之间比较（类似 obj1 > obj2），或者跟一个原始类型比较（obj == 5），对象都会被转换为原始值。

// *************************************************************************************************

// 【对象的克隆与合并】Object.assign

// [合并对象]：Object.assign(target, source1, source2,...)
let user = { name: 'John' }
let permissions1 = { canView: true }
let permissions2 = { canEdit: true }
Object.assign(user, permissions1, permissions2)
console.log(user) // { name: 'John', canView: true, canEdit: true }

// [浅克隆对象]：let clone = Object.assign({}, obj)
let obj = { name: 'John', age: 30 }
let clone = Object.assign({}, obj) // 将 obj 对象中的所有属性拷贝到了一个空对象中，并返回这个新对象（克隆对象推荐使用 clone = {...obj} 语法）。
console.log(clone) // { name: 'John', age: 30 }

// *************************************************************************************************

// 【深克隆】
let objs = {
	name: 'Jake',
	sizes: {
		height: 182,
		width: 50,
	},
}

// 浅拷贝对象，无法解决对象内部引用类型的拷贝（内部对象还是指向同一个地址）。
// console.log(objs.sizes.height) // 182
// let cloneObjs = Object.assign({}, objs)
// console.log(objs.sizes == cloneObjs.sizes) // true 对象内部的 sizes 对象，还是都指向同一个地址（外部已经拷贝一份出来了，不指向同一个地址）。
// objs.sizes.height = 175
// console.log(cloneObjs.sizes.height) // 175

// 使用浏览器最新提供的 api 进行深拷贝
let cloneObjs = structuredClone(objs) // 深拷贝对象，解决对象内部的
console.log(cloneObjs)
console.log(objs.sizes == cloneObjs.sizes) // false

// *************************************************************************************************

// 【总结】

// 声明一个对象
let o = {
	name: 'Ning',
}

// 复制给另一个变量（但实际上只是复制了对对象的引用）
let o2 = o

console.log(o === o2) // true 两个对象还是相等
o.name = 'Nina'
console.log(o2.name) // Nina 改变第一个对象的值，第二个对象也会跟着改变。

// 合并对象
let h1 = { name: 'Ben' }
let h2 = { age: 25 }
Object.assign(h1, h2) // 将 h2 的属性合并到 h1 中
console.log(h1) // { name: 'Ben', age: 25 }

// 浅克隆对象
let j1 = { name: 'Jane', age: 30 }
let j2 = Object.assign({}, j1)
j1.name = 'Jenny'
console.log(j2.name) // Jane 已经对 j1 进行了克隆，所以 j2 的 name 属性值不会跟着改变。

// 浅克隆存在的问题：
let c1 = { name: 'Tom', sizes: { height: 175, width: 60 } }
let c2 = Object.assign({}, c1) // 将 c1 复制到 {} 中，并返回一个新对象。
console.log(c1 === c2) // false 现在 c2 确实是对 c1 复制了一份出来，而不是复制的引用。但是内部的 sizes 对象还是指向同一个地址。
console.log(c1.sizes === c2.sizes) // true  c1 和 c2 内部的 sizes 对象还是指向同一个地址。

// 深克隆对象
let d1 = { name: 'Dave', sizes: { height: 165, width: 55 } }
let d2 = structuredClone(d1) // 使用浏览器提供的 api 进行深拷贝
console.log(d1.sizes === d2.sizes) // false 内部的 sizes 对象不再指向同一个地址。

// const 声明的常量对象，对象内部的属性值还是可以被修改。
const e1 = { name: 'Eve' }
e1.name = 'Eva'
console.log('name' in e1) // true
console.log(e1.name) // Eva
delete e1.name
console.log(e1) // {}
// e1 = 123 // 报错，整个值的替换是不被允许的。
// * 如果想要实现完全的 常量对象 可以使用 Object.freeze() 方法。
